/*
 Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
 Copyright (C) 2014 Sony Computer Entertainment Inc.

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Library General Public
 License as published by the Free Software Foundation; either
 version 2 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Library General Public License for more details.

 You should have received a copy of the GNU Library General Public License
 along with this library; see the file COPYING.LIB.  If not, write to
 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 Boston, MA 02110-1301, USA.
 */

#include "config.h"
#include "AcagiBitmapTexture.h"

#include "AcagiCompositor.h"
#include "GraphicsLayer.h"
#include "ImageBuffer.h"
#include "NotImplemented.h"

#if USE(ACCELERATED_COMPOSITING) && USE(ACAGI)

#define DBG_TRACE printf("%s %d\n", __PRETTY_FUNCTION__, __LINE__)

namespace WebCore {

AcagiBitmapTexture::AcagiBitmapTexture(AcagiCompositor* compositor)
    : m_flags(0)
    , m_compositor(compositor)
    , m_shouldClear(true)
{
}

AcagiBitmapTexture::~AcagiBitmapTexture()
{
}

IntSize AcagiBitmapTexture::size() const
{
    return textureSize();
}

void AcagiBitmapTexture::updateContents(Image* image, const IntRect& targetRect, const IntPoint& offset, UpdateContentsFlag updateContentsFlag)
{
    if (!image)
        return;
    NativeImagePtr frameImage = image->nativeImageForCurrentFrame();
    if (!frameImage)
        return;

    int bytesPerLine;
    const char* imageData;

    cairo_surface_t* surface = frameImage.get();
    imageData = reinterpret_cast<const char*>(cairo_image_surface_get_data(surface));
    bytesPerLine = cairo_image_surface_get_stride(surface);

    updateContents(imageData, targetRect, offset, bytesPerLine, updateContentsFlag);
}

void AcagiBitmapTexture::updateContents(AcagiCompositor* compositor, GraphicsLayer* sourceLayer, const IntRect& targetRect, const IntPoint& targetOffset, const FloatRect& sourceRect, UpdateContentsFlag updateContentsFlag)
{
    OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(targetRect.size());
    GraphicsContext* context = imageBuffer->context();

    IntRect enclosingSourceRect = enclosingIntRect(sourceRect);
    context->translate(-targetOffset.x(), -targetOffset.y());
    context->translate(-targetRect.x(), -targetRect.y());
    context->scale(FloatSize(targetRect.width() / sourceRect.width(), targetRect.height() / sourceRect.height()));
    context->translate(sourceRect.x() - enclosingSourceRect.x(), sourceRect.y() - enclosingSourceRect.y());
    sourceLayer->paintGraphicsLayerContents(*context, enclosingSourceRect);

    RefPtr<Image> image = imageBuffer->copyImage(DontCopyBackingStore);

    updateContents(image.get(), targetRect, IntPoint(), updateContentsFlag);
}

void AcagiBitmapTexture::updateContents(const void* srcData, const IntRect& targetRect, const IntPoint& sourceOffset, int bytesPerLine, UpdateContentsFlag)
{
    if (!isValid())
        return;
    m_texture->updateContents(srcData, targetRect, sourceOffset, bytesPerLine);
}

bool AcagiBitmapTexture::isValid() const
{
    return m_texture ? m_texture->isValid() : false;
}

int AcagiBitmapTexture::bpp() const
{
    notImplemented();
    return 0;
}

bool AcagiBitmapTexture::canReuseWith(const IntSize& contentsSize, Flags)
{
    return contentsSize == textureSize();
}

void AcagiBitmapTexture::duplicate(const AcagiBitmapTexture& rhs)
{
    m_flags = rhs.m_flags;
    m_contentSize = rhs.m_contentSize;
    m_shouldClear = false;
    m_texture = PlatformTexture::duplicate(rhs.m_texture);
}

void AcagiBitmapTexture::didReset()
{
    m_shouldClear = true;
    if (m_contentSize == textureSize())
        return;

    resetTexture(m_contentSize);
}

void AcagiBitmapTexture::resetTexture(const IntSize& newSize)
{
    m_texture = m_compositor->m_graphics->createTexture(newSize);
}


} // namespace

#endif
